import lodash from 'lodash'
import { Injectable } from '@nestjs/common'
import { InjectModel } from '@app/transformers/model.transformer'
import { MongooseModel, MongooseDoc } from '@app/interfaces/mongoose.interface'
import { Option, Blocklist, DEFAULT_OPTION } from './option.model'

@Injectable()
export class OptionService {
  constructor(@InjectModel(Option) private readonly optionModel: MongooseModel<Option>) { }

  public async ensureAppOption(): Promise<MongooseDoc<Option>> {
    const option = await this.optionModel.findOne().exec()
    return option || (await this.optionModel.create({ ...DEFAULT_OPTION }))
  }

  public async putOption(newOption: Option): Promise<Option> {
    // delete _id, likes fileds
    Reflect.deleteProperty(newOption, '_id')
    Reflect.deleteProperty(newOption, 'meta')

    await this.optionModel.updateOne({}, newOption).exec()

    // update cache when option updated
    return await this.ensureAppOption()
  }

  public async appendToBlocklist(payload: { ips: string[]; emails: string[] }): Promise<Blocklist> {
    const option = await this.ensureAppOption()
    option.blocklist.ips = lodash.uniq([...option.blocklist.ips, ...payload.ips])
    option.blocklist.mails = lodash.uniq([...option.blocklist.mails, ...payload.emails])
    await option.save()
    return option.blocklist
  }

  public async removeFromBlocklist(payload: { ips: string[]; emails: string[] }): Promise<Blocklist> {
    const option = await this.ensureAppOption()
    option.blocklist.ips = option.blocklist.ips.filter((ip) => !payload.ips.includes(ip))
    option.blocklist.mails = option.blocklist.mails.filter((email) => !payload.emails.includes(email))
    await option.save()
    return option.blocklist
  }

  public async incrementLikes(): Promise<number> {
    const option = await this.ensureAppOption()
    option.meta.likes++
    await option.save({ timestamps: false })
    return option.meta.likes
  }
}
